/**
 * 安全音频服务 - 防下载流媒体播放
 */
class SecureAudioService {
  constructor() {
    this.audioContext = null
    this.activeTokens = new Map()
    this.audioBuffers = new Map()
    this.chunkCache = new Map()
  }

  /**
   * 初始化 Web Audio API
   */
  async initAudioContext() {
    try {
      if (!this.audioContext) {
        this.audioContext = new (window.AudioContext || window.webkitAudioContext)()
      }
      
      if (this.audioContext.state === 'suspended') {
        await this.audioContext.resume()
      }
      
      return this.audioContext
    } catch (error) {
      console.warn('AudioContext初始化延迟，将在用户交互时启动:', error.message)
      return null
    }
  }

  /**
   * 获取安全音频播放URL
   */
  async getSecureAudioUrl(filename) {
    try {
      const response = await fetch('http://localhost:2025/api/files/audio-token', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${localStorage.getItem('token')}`,
        },
        credentials: 'include',
        body: JSON.stringify({ filename })
      })

      if (!response.ok) {
        throw new Error('获取音频令牌失败')
      }

      const data = await response.json()
      
      // 存储令牌信息
      this.activeTokens.set(filename, {
        token: data.token,
        url: `http://localhost:2025${data.url}`,
        expires: data.expires
      })

      return data
    } catch (error) {
      console.error('获取安全音频URL失败:', error)
      throw error
    }
  }

  /**
   * 创建受保护的音频元素
   */
  async createProtectedAudio(filename) {
    try {
      // 获取安全令牌
      const tokenData = await this.getSecureAudioUrl(filename)
      
      // 创建音频元素，使用安全URL
      const audio = new Audio()
      
      // 设置防下载属性
      audio.crossOrigin = 'use-credentials'
      audio.preload = 'none'
      
      // 创建安全的Blob URL
      const secureUrl = await this.createSecureBlobUrl(tokenData.url)
      audio.src = secureUrl
      
      // 添加事件监听器
      this.setupAudioEventListeners(audio, filename)
      
      return audio
    } catch (error) {
      console.error('创建受保护音频失败:', error)
      throw error
    }
  }

  /**
   * 创建安全的Blob URL
   */
  async createSecureBlobUrl(secureUrl) {
    try {
      const response = await fetch(secureUrl, {
        credentials: 'include',
        headers: {
          'Accept': 'audio/*',
          'Cache-Control': 'no-cache'
        }
      })

      if (!response.ok) {
        throw new Error('获取音频数据失败')
      }

      // 读取加密的音频数据
      const encryptedData = await response.arrayBuffer()
      
      // 解混淆数据
      const audioData = this.deobfuscateAudioData(new Uint8Array(encryptedData))
      
      // 创建临时Blob
      const blob = new Blob([audioData], { type: 'audio/mpeg' })
      const blobUrl = URL.createObjectURL(blob)
      
      // 定时清理Blob URL
      setTimeout(() => {
        URL.revokeObjectURL(blobUrl)
      }, 300000) // 5分钟后清理
      
      return blobUrl
    } catch (error) {
      console.error('创建安全Blob URL失败:', error)
      throw error
    }
  }

  /**
   * 解混淆音频数据
   */
  deobfuscateAudioData(data) {
    const chunkSize = 32768
    const deobfuscated = new Uint8Array(data.length)
    
    for (let i = 0; i < data.length; i += chunkSize) {
      const chunkIndex = Math.floor(i / chunkSize)
      const chunkEnd = Math.min(i + chunkSize, data.length)
      
      for (let j = i; j < chunkEnd; j++) {
        deobfuscated[j] = data[j] ^ (chunkIndex & 0xFF)
      }
    }
    
    return deobfuscated
  }

  /**
   * 设置音频事件监听器
   */
  setupAudioEventListeners(audio, filename) {
    // 防止右键菜单
    audio.addEventListener('contextmenu', (e) => {
      e.preventDefault()
      return false
    })

    // 防止拖拽
    audio.addEventListener('dragstart', (e) => {
      e.preventDefault()
      return false
    })

    // 监听加载错误
    audio.addEventListener('error', (e) => {
      console.error('音频播放错误:', e)
      this.handleAudioError(filename)
    })

    // 播放结束时清理资源
    audio.addEventListener('ended', () => {
      this.cleanupAudioResources(filename)
    })
  }

  /**
   * 处理音频错误
   */
  async handleAudioError(filename) {
    console.log('音频播放出错，尝试重新获取令牌')
    
    // 清理过期令牌
    this.activeTokens.delete(filename)
    
    // 重新获取令牌
    try {
      await this.getSecureAudioUrl(filename)
    } catch (error) {
      console.error('重新获取音频令牌失败:', error)
    }
  }

  /**
   * 清理音频资源
   */
  cleanupAudioResources(filename) {
    // 清理缓存
    this.audioBuffers.delete(filename)
    this.chunkCache.delete(filename)
    
    // 清理过期令牌
    const tokenInfo = this.activeTokens.get(filename)
    if (tokenInfo && Date.now() > tokenInfo.expires) {
      this.activeTokens.delete(filename)
    }
  }

  /**
   * 检查令牌是否有效
   */
  isTokenValid(filename) {
    const tokenInfo = this.activeTokens.get(filename)
    return tokenInfo && Date.now() < tokenInfo.expires
  }

  /**
   * 预加载音频元数据
   */
  async preloadAudioInfo(filename) {
    try {
      const response = await fetch('http://localhost:2025/api/files/audio-info', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        credentials: 'include',
        body: JSON.stringify({ filename })
      })

      if (response.ok) {
        return await response.json()
      }
    } catch (error) {
      console.error('预加载音频信息失败:', error)
    }
    return null
  }

  /**
   * 销毁服务，清理所有资源
   */
  destroy() {
    // 清理所有缓存
    this.activeTokens.clear()
    this.audioBuffers.clear()
    this.chunkCache.clear()
    
    // 关闭音频上下文
    if (this.audioContext) {
      this.audioContext.close()
      this.audioContext = null
    }
  }
}

// 创建单例实例
const secureAudioService = new SecureAudioService()

export default secureAudioService 